﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using log4net;
using log4net.Appender;
using log4net.Layout;
using log4net.Repository.Hierarchy;

namespace One.Framework.Util
{
    /// <summary>
    /// Logging
    /// </summary>
    public class LoggingHelper
    {
        /// <summary>
        /// LogManager
        /// </summary>
        public static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        #region Log Level

        /// <summary>
        ///  치명적 오류
        /// </summary>
        /// <param name="message">메세지</param>
        public static void Fatal(object message)
        {
            Fatal(message, string.Empty);
        }

        /// <summary>
        ///  치명적 오류
        /// </summary>
        /// <param name="message">메세지</param>
        /// <param name="connectionString">DB연결소스</param>
        public static void Fatal(object message, string connectionString)
        {
            Logging(connectionString);

            if (log.IsFatalEnabled)
                log.Fatal(message);
        }

        /// <summary>
        /// 장애
        /// </summary>
        /// <param name="message">메세지</param>
        public static void Error(object message)
        {
            Error(message, string.Empty);
        }

        /// <summary>
        /// 장애
        /// </summary>
        /// <param name="message">메세지</param>
        /// <param name="connectionString">DB연결소스</param>
        public static void Error(object message, string connectionString)
        {
            Logging(connectionString);

            if (log.IsErrorEnabled)
                log.Error(message);
        }

        /// <summary>
        /// 경고
        /// </summary>
        /// <param name="message">메세지</param>
        public static void Warn(object message)
        {
            Warn(message, string.Empty);
        }

        /// <summary>
        /// 경고
        /// </summary>
        /// <param name="message">메세지</param>
        /// <param name="connectionString">DB연결소스</param>
        public static void Warn(object message, string connectionString)
        {
            Logging(connectionString);

            if (log.IsWarnEnabled)
                log.Warn(message);
        }

        /// <summary>
        /// 정보
        /// </summary>
        /// <param name="message">메세지</param>
        public static void Info(object message)
        {
            Info(message, string.Empty);
        }

        /// <summary>
        /// 정보
        /// </summary>
        /// <param name="message">메세지</param>
        /// <param name="connectionString">DB연결소스</param>
        public static void Info(object message, string connectionString)
        {
            Logging(connectionString);

            if (log.IsInfoEnabled)
                log.Info(message);
        }

        /// <summary>
        /// 디버그
        /// </summary>
        /// <param name="message">메세지</param>
        public static void Debug(object message)
        {
            Debug(message, string.Empty);
        }

        /// <summary>
        /// 디버그
        /// </summary>
        /// <param name="message">메세지</param>
        /// <param name="connectionString">DB연결소스</param>
        public static void Debug(object message, string connectionString)
        {
            Logging(connectionString);

            if (log.IsDebugEnabled)
                log.Debug(message);
        }

        #endregion // Log Level

        /// <summary>
        /// Appender 추가
        /// </summary>
        /// <param name="connectionString">DB연결소스</param>
        private static void Logging(string connectionString)
        {
            Logger root;
            root = ((Hierarchy)LogManager.GetRepository()).Root;
            root.AddAppender(GetRollingFileAppender());
            root.AddAppender(GetFileAppender());

            if (connectionString.Length > 0)
            {
                root.AddAppender(GetAdoNetAppender(connectionString));
            }

            root.Level = log4net.Core.Level.All;
            root.Repository.Configured = true;
        }

        /// <summary>
        /// RollingFileAppender
        /// </summary>
        /// <returns></returns>
        private static RollingFileAppender GetRollingFileAppender()
        {
            RollingFileAppender lAppender = new RollingFileAppender();

            lAppender.Name = "RollingFile";
            lAppender.AppendToFile = true;
            lAppender.File = @"C:\TEMP\Log4Net.log";
            lAppender.Layout = new
            log4net.Layout.PatternLayout("%d [%t] %-5p %c - %m%n");
            lAppender.Threshold = log4net.Core.Level.All;
            lAppender.ActivateOptions();

            return lAppender;
        }

        /// <summary>
        /// FileAppender
        /// </summary>
        /// <returns></returns>
        private static FileAppender GetFileAppender()
        {
            FileAppender lAppender = new FileAppender();

            lAppender.Name = "File";
            lAppender.AppendToFile = true;
            lAppender.File = @"C:\TEMP\Log4Net.log";
            lAppender.Layout = new
            log4net.Layout.PatternLayout("%d [%t] %-5p %c - %m%n");
            lAppender.Threshold = log4net.Core.Level.All;
            lAppender.ActivateOptions();

            return lAppender;
        }

        /// <summary>
        /// AdoNetAppender
        /// </summary>
        /// <returns></returns>
        private static AdoNetAppender GetAdoNetAppender(string connectionString)
        {
            AdoNetAppender lAppender = new AdoNetAppender();
            lAppender.Name = "AdoNet";

            lAppender.CommandType = System.Data.CommandType.Text;
            lAppender.ConnectionType = "Oracle.DataAccess.Client.OracleConnection, Oracle.DataAccess, Version=2.102.2.20, Culture=neutral, PublicKeyToken=89b483f429c47342";
            lAppender.CommandText = "INSERT INTO T_LOG (LOG_UID, LOG_DATE, LOG_LEVEL, LOG_IDENTITY, LOG_MESSAGE, LOG_EXCEPTION) VALUES (sys_guid(), sysdate, :log_level, :log_identity, :log_message, :log_exception)";

            lAppender.ConnectionString = connectionString;
            lAppender.BufferSize = 0;

            AddAppendParamSet(lAppender, "log_level", System.Data.DbType.String, new log4net.Layout.PatternLayout("%level"));
            AddAppendParamSet(lAppender, "log_identity", System.Data.DbType.String, new log4net.Layout.PatternLayout("%identity"));
            AddAppendParamSet(lAppender, "log_message", System.Data.DbType.String, new log4net.Layout.PatternLayout("%m"));
            AddAppendParamSet(lAppender, "log_exception", System.Data.DbType.String, new log4net.Layout.PatternLayout("%exception"));

            lAppender.ActivateOptions();

            return lAppender;


        }

        /// <summary>
        /// Appender 파라미터 추가
        /// </summary>
        /// <param name="appender"></param>
        /// <param name="ParameterName"></param>
        /// <param name="dbtype"></param>
        /// <param name="layout"></param>
        private static void AddAppendParamSet(AdoNetAppender appender, string ParameterName, System.Data.DbType dbtype, ILayout layout)
        {
            AdoNetAppenderParameter param = new AdoNetAppenderParameter();
            param.DbType = dbtype;
            param.ParameterName = ParameterName;
            param.Layout = new Layout2RawLayoutAdapter(layout);

            appender.AddParameter(param);
        }
    }
}
